package com.heima.wemedia.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.heima.api.ArticleClient;
import com.heima.common.exception.CustomException;
import com.heima.common.util.ImageUrlUtil;
import com.heima.common.util.OcrImageUtil;
import com.heima.common.util.ScanLocalImage;
import com.heima.common.util.TextModerationPlusDemo;
import com.heima.file.service.FileStorageService;
import com.heima.model.article.dto.ArticleDto;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.wemedia.pojos.WmNews;
import com.heima.model.wemedia.pojos.WmSensitive;
import com.heima.model.wemedia.pojos.WmUser;
import com.heima.utils.common.SensitiveWordUtil;
import com.heima.wemedia.mapper.SenstiveMapper;
import com.heima.wemedia.service.ChannelService;
import com.heima.wemedia.service.NewsService;
import com.heima.wemedia.service.WmNewAuditService;
import com.heima.wemedia.service.WmUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @projectName: heima-leadnews
 * @package: com.heima.wemedia.service.impl
 * @className: WmNewAuditServiceImpl
 * @author: 躺着认真玩
 * @description: 文章审核
 * @date: 2025/5/21 12:55
 * @version: 1.0
 */
@Service
public class WmNewAuditServiceImpl implements WmNewAuditService {
    @Autowired
    private ArticleClient articleClient;
    @Autowired
    private ChannelService channelService;
    @Autowired
    private WmUserService wmUserService;
    @Autowired
    private NewsService newsService;
    @Autowired
    private OcrImageUtil ocrImageUtil;
    @Override
    @Async
    public void autoAudit(WmNews wmNews) throws Exception {
        // 参数校验
        if (wmNews == null ) {
            throw new CustomException(AppHttpCodeEnum.DATA_NOT_EXIST);
        }
        // OCR图片识别
        Boolean o = ocrHandImages(wmNews);
        if(!o)return;
        // DFA算法对文本进行审核
        Boolean r = DfaHand(wmNews );
        if (!r)return;
        //文本审核
        // boolean b = handText(wmNews);
        // if (!b) return;
        // 图片审核
        // Boolean b1 = handImages(wmNews);
        // if (!b1)return;
        // 自媒体  App端  文章数据进行同步
        submitArticle(wmNews);
        return;
    }

    private Boolean ocrHandImages(WmNews wmNews) throws Exception {
        // 抽取图片
        List<String> list = getImages(wmNews);
        // 抽取图片中的文字
        StringBuilder sb = new StringBuilder();
        for (String s : list) {
            byte[] bytes = fileStorageService.downLoadFile(s);
            String content = ocrImageUtil.getImageText(bytes);
            if (content != null) {
                sb.append(content);
            }
        }
        // DFA审核
        Boolean b = fdaByContent(wmNews, sb.toString());
        return b;
    }

    private void submitArticle(WmNews wmNews) {
        // app端发布文章
        ArticleDto articleDto = BeanUtil.copyProperties(wmNews, ArticleDto.class);
        articleDto.setId(wmNews.getArticleId());
        articleDto.setLayout(wmNews.getType());

        WmUser wu = wmUserService.getById(wmNews.getUserId());
        articleDto.setAuthorId(Long.valueOf(wu.getApUserId()));
        articleDto.setAuthorName(wu.getName());
        String name = channelService.getById(wmNews.getChannelId()).getName();
        articleDto.setChannelName(name);
        articleDto.setPublishTime(new Date());
        ResponseResult responseResult = articleClient.submitArticle(articleDto);
        if (responseResult.getCode() == 200) {
            //     修改自媒体端状态已发布  9
            Map<String,Object> map = (Map<String, Object>) responseResult.getData();

            newsService.lambdaUpdate().eq(WmNews::getId,wmNews.getId())
                    .set(WmNews::getStatus,(short)9)
                    .set(WmNews::getArticleId,Long.valueOf(map.get("articleId").toString()))
                    .set(WmNews::getPublishTime,map.get("publishTime"))
                    .update();
        }
    }

    @Autowired
    private SenstiveMapper senstiveMapper;

    private Boolean DfaHand(WmNews wmNews) {
        // 抽取校验内容
        String content = wmNews.getTitle() + getText(wmNews.getContent());
        return fdaByContent(wmNews, content);
    }

    private Boolean fdaByContent(WmNews wmNews, String content) {
        Boolean falg = true;
        // 校验
        List<WmSensitive> wmSensitives = senstiveMapper.selectList(new LambdaQueryWrapper<WmSensitive>());
        List<String> sensitives = wmSensitives.stream().map(WmSensitive::getSensitives).collect(Collectors.toList());
        SensitiveWordUtil.initMap(sensitives);
        Map<String, Integer> map = SensitiveWordUtil.matchWords(content);
        if (!map.isEmpty()){
        //     对自媒体文章进行修改
            newsService.lambdaUpdate()
                    .eq(WmNews::getId, wmNews.getId())
                    .set(WmNews::getStatus,(short)2)
                    .set(WmNews::getReason,"文章含有敏感词:"+map)
                    .update();
            falg = false;
        }

        return falg;
    }

    @Autowired
    private ImageUrlUtil imageUrlUtil;
    @Autowired
    private ScanLocalImage scanLocalImage;
    @Autowired
    private FileStorageService fileStorageService;


    /**
     *图片审核
     */
    private Boolean handImages(WmNews wmNews) {
        Boolean flag = false;
        // 参数校验
        if (wmNews == null) {
            throw new CustomException(AppHttpCodeEnum.DATA_NOT_EXIST);
        }
        // 抽取图片
        List<String> list = getImages(wmNews);
        // 图片审核
        for (String s : list) {
            try {
                // 获取图片字节数组 图片后缀
                byte[] image = fileStorageService.downLoadFile(s);
                String suffix = StrUtil.split(s, ".").get(1);

                Map<String, String> map = scanLocalImage.imageAduit(suffix, image);
                // Map<String, String> map = imageUrlUtil.aduitImages(s);
                if (map.get("risklevel").equals("high")) {
                    // 审核不通过 修改自媒体文章  理由 审核失败2
                    newsService.lambdaUpdate()
                            .eq(WmNews::getId,wmNews.getId())
                            .set(WmNews::getReason,map.get("description"))
                            .set(WmNews::getStatus,(short)2)
                            .update();
                    return flag;
                }
                if (map.get("risklevel").equals("medium") || map.get("risklevel").equals("low")) {
                    // 审核不通过 修改自媒体文章  理由 人工审核3
                    newsService.lambdaUpdate()
                            .eq(WmNews::getId,wmNews.getId())
                            .set(WmNews::getReason,map.get("description"))
                            .set(WmNews::getStatus,(short)3)
                            .update();
                    return flag;
                }
            } catch (Exception e) {
                throw new CustomException(AppHttpCodeEnum.IMAGEREVIEWFAILED);
            }

        }
        // 审核通过(待发布) 8
        newsService.lambdaUpdate()
                .eq(WmNews::getId,wmNews.getId())
                .set(WmNews::getStatus,(short)8)
                .update();

        return true;

    }

    private List<String> getImages(WmNews wmNews) {
        // 内容中的图片
        List<Map> list = JSONUtil.toList(JSONUtil.parseArray(wmNews.getContent()), Map.class);
        List<String> result = new ArrayList<>();
        for (Map map : list) {
            if (map.get("type").toString().equals("image")) {
                String pickerUrl = map.get("value").toString();
                result.add(pickerUrl);
            }
        }
    //     封面中的图片
        if (!wmNews.getImages().isEmpty()) {
            List<String> split = StrUtil.split(wmNews.getImages(), ",");
            result = Stream.concat(result.stream(), split.stream())
                    .distinct()
                    .collect(Collectors.toList());
        }
        return result;
    }

    @Autowired
    private TextModerationPlusDemo textModerationPlusDemo;


    /**
     *文本审核文本
     */
    private boolean handText(WmNews wmNews) throws Exception {
        Boolean flag = false;
        // 参数校验
        if (wmNews.getContent() == null) {
            throw new CustomException(AppHttpCodeEnum.DATA_NOT_EXIST);
        }
        // 抽取文章内文本内容
        String text = getText(wmNews.getContent());
        // 文本审核
        try {
            Map<String,String> map = textModerationPlusDemo.greeText(text + "-" + wmNews.getTitle());
            // 审核成功
            if (map.get("riskLevel").equals("none") ) {
                return true;
            }
            if (map.get("riskLevel").equals("medium") || map.get("riskLevel").equals("low")) {
                //     修该自媒体文章状态为3  拒绝理由-文章内容有不确定因素
                newsService.lambdaUpdate()
                        .eq(WmNews::getId,wmNews.getId())
                        .set(WmNews::getReason,map.get("description"))
                        .set(WmNews::getStatus,(short)3)
                        .update();
                flag = false;
            }
            if (map.get("riskLevel").equals("high")) {
                //     修该自媒体文章状态为2  拒绝理由-文章内容违规
                newsService.lambdaUpdate()
                        .eq(WmNews::getId,wmNews.getId())
                        .set(WmNews::getReason,map.get("description"))
                        .set(WmNews::getStatus,(short)2)
                        .update();
                flag = false;
            }
        } catch (Exception e) {
            throw new CustomException(AppHttpCodeEnum.ARTICLEREVIEWFAILED);
        }

        return flag;

    }

    private String getText(String content) {
        List<Map> list = JSONUtil.toList(JSONUtil.parseArray(content), Map.class);
        StringBuilder sb = new StringBuilder();
        for (Map map : list) {
            if (map.get("type").toString().equals("text")) {
                String text = map.get("value").toString();
                sb.append(text);
            }
        }
        return sb.toString();
    }
}
